use crate::rtsp::rtp::errors::{PackerError, UnPackerError};
use crate::rtsp::rtp::rtp_header::RtpHeader;
use crate::rtsp::rtp::utils::{
    OnFrameFn, OnRtpPacketFn, OnRtpPacketFn2, TPacker, TRtpReceiverForRtcp, TUnPacker, Unmarshal,
};
use crate::rtsp::rtp::RtpPacket;
use async_trait::async_trait;
use byteorder::BigEndian;
use bytes::{BufMut, BytesMut};
use bytesio::bytes_reader::BytesReader;
use bytesio::bytesio::TNetIO;
use std::sync::Arc;
use streamhub::define::FrameData;
use tokio::sync::Mutex;

// RtpAacPacker 结构体，将 AAC 音频数据打包成 RTP 数据包
pub struct RtpAacPacker {
    // 头部信息
    header: RtpHeader,
    // RTP 数据包回调函数，将打包好的数据包发送
    on_packet_handler: Option<OnRtpPacketFn>,
    // RTCP 回调函数
    on_packet_for_rtcp_handler: Option<OnRtpPacketFn2>,
    // 网络对象
    io: Arc<Mutex<Box<dyn TNetIO + Send + Sync>>>,
}

impl RtpAacPacker {
    pub fn new(
        payload_type: u8,
        ssrc: u32,
        init_seq: u16,
        io: Arc<Mutex<Box<dyn TNetIO + Send + Sync>>>,
    ) -> Self {
        RtpAacPacker {
            header: RtpHeader {
                payload_type,
                seq_number: init_seq,
                ssrc,
                version: 2,
                marker: 1,
                ..Default::default()
            },
            io,
            on_packet_handler: None,
            on_packet_for_rtcp_handler: None,
        }
    }
}

#[async_trait]
impl TPacker for RtpAacPacker {
    // 将 AAC 音频数据打包成 RTP 数据包
    async fn pack(&mut self, nalus: &mut BytesMut, timestamp: u32) -> Result<(), PackerError> {
        // 设置 RTP 头部的时间戳
        self.header.timestamp = timestamp;

        // 获取要打包的 AAC 数据的长度
        let data_len = nalus.len();
        // 创建一个新的 RTP 数据包，使用当前的 RTP 头部信息
        let mut packet = RtpPacket::new(self.header.clone());

        // 按照 RTP AAC 打包规则，在负载中添加特定信息
        // 写入 16 到负载中，具体含义根据协议规定
        packet.payload.put_u16(16);
        // 写入数据长度的高 3 位
        packet.payload.put_u8((data_len >> 5) as u8);
        // 写入数据长度的低 5 位，并左移 3 位
        packet.payload.put_u8(((data_len & 0x1F) << 3) as u8);
        // 将 AAC 数据添加到 RTP 数据包的负载中
        packet.payload.put(nalus);

        if let Some(f) = &self.on_packet_for_rtcp_handler {
            // 如果存在 RTCP 处理回调函数，调用该函数处理当前数据包
            f(packet.clone()).await;
        }

        if let Some(f) = &self.on_packet_handler {
            // 如果存在数据包处理回调函数，调用该函数发送当前数据包
            f(self.io.clone(), packet).await?;
        }

        // 递增序列号
        self.header.seq_number += 1;

        Ok(())
    }

    fn on_packet_handler(&mut self, f: OnRtpPacketFn) {
        self.on_packet_handler = Some(f);
    }
}

impl TRtpReceiverForRtcp for RtpAacPacker {
    fn on_packet_for_rtcp_handler(&mut self, f: OnRtpPacketFn2) {
        self.on_packet_for_rtcp_handler = Some(f);
    }
}

// RtpAacUnPacker 结构体，将 RTP 数据包解包为 AAC 音频帧
#[derive(Default)]
pub struct RtpAacUnPacker {
    // 处理解包后帧数据的回调函数
    on_frame_handler: Option<OnFrameFn>,
    // 处理 RTCP 相关 RTP 数据包的回调函数
    on_packet_for_rtcp_handler: Option<OnRtpPacketFn2>,
}

// 以下注释为 RTP AAC 数据包的结构说明
// +---------+-----------+-----------+---------------+
// | RTP     | AU Header | Auxiliary | Access Unit   |
// | Header  | Section   | Section   | Data Section  |
// +---------+-----------+-----------+---------------+
// 	<----------RTP Packet Payload----------->
//
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
// |AU-headers-length|AU-header|AU-header|      |AU-header|padding|
// |                 |   (1)   |   (2)   |      |   (n)   | bits  |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+

// Au-headers-length 2 bytes
impl RtpAacUnPacker {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }
}

#[async_trait]
impl TUnPacker for RtpAacUnPacker {
    // 将 RTP 数据包解包为 AAC 音频帧
    async fn unpack(&mut self, reader: &mut BytesReader) -> Result<(), UnPackerError> {
        // 将字节流反序列化为 RtpPacket 实例
        let rtp_packet = RtpPacket::unmarshal(reader)?;

        if let Some(f) = &self.on_packet_for_rtcp_handler {
            // 如果存在 RTCP 处理回调函数，调用该函数处理当前数据包
            f(rtp_packet.clone()).await;
        }

        // 创建一个新的字节读取器，用于读取 RTP 数据包的负载数据
        let mut reader_payload = BytesReader::new(rtp_packet.payload);

        // 读取 AU 头部长度（以位为单位），并将其转换为字节数
        let au_headers_length = (reader_payload.read_u16::<BigEndian>()? + 7) / 8;
        // 每个 AU 头部的长度为 2 字节
        let au_header_length = 2;
        // 计算 AU 的数量
        let aus_number = au_headers_length / au_header_length;

        // 用于存储每个 AU 的长度
        let mut au_lengths = Vec::new();
        for _ in 0..aus_number {
            // 读取每个 AU 头部中的长度信息
            let au_length = (((reader_payload.read_u8()? as u16) << 8)
                | ((reader_payload.read_u8()? as u16) & 0xF8)) as usize;
            // 将长度从位转换为字节，并添加到 au_lengths 向量中
            au_lengths.push(au_length / 8);
        }

        // 记录调试信息，包含 AU 头部长度、AU 数量和每个 AU 的长度
        log::debug!(
            "send audio : au_headers_length :{}, aus_number: {}, au_lengths: {:?}",
            au_headers_length,
            aus_number,
            au_lengths,
        );

        // 遍历每个 AU 的长度
        for (i, item) in au_lengths.iter().enumerate() {
            // 读取当前 AU 的数据
            let au_data = reader_payload.read_bytes(*item)?;
            if let Some(f) = &self.on_frame_handler {
                // 如果存在帧处理回调函数，调用该函数处理当前音频帧
                f(FrameData::Audio {
                    // 根据索引计算时间戳偏移，添加到 RTP 头部的时间戳上
                    timestamp: rtp_packet.header.timestamp + i as u32 * 1024,
                    data: au_data,
                })?;
            }
        }

        Ok(())
    }

    // 设置处理解包后帧数据的回调函数
    fn on_frame_handler(&mut self, f: OnFrameFn) {
        self.on_frame_handler = Some(f);
    }
}

// 处理 RTCP 相关的 RTP 数据包
impl TRtpReceiverForRtcp for RtpAacUnPacker {
    fn on_packet_for_rtcp_handler(&mut self, f: OnRtpPacketFn2) {
        self.on_packet_for_rtcp_handler = Some(f);
    }
}
